package com.example.AIstudy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.AIstudy.DTO.ProsetDTO;
import com.example.AIstudy.dao.ExerciseDao;
import com.example.AIstudy.dao.LikedDao;
import com.example.AIstudy.dao.ProSetDao;
import com.example.AIstudy.dao.SetAndExeDao;
import com.example.AIstudy.domain.*;
import com.example.AIstudy.exception.AIstudyException;
import com.example.AIstudy.service.ProSetService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class ProSetServiceImpl extends ServiceImpl<ProSetDao, ProSet> implements ProSetService {

    @Autowired
    ProSetDao proSetDao;

    @Autowired
    SetAndExeDao setAndExeDao;

    @Autowired
    ExerciseDao exeDao;

    @Autowired
    LikedDao likedDao;

    @Override
    @Transactional(rollbackFor = AIstudyException.class)
    public void insertProSet(ProSet proSet) throws AIstudyException {
        try{
            //插入套题的信息，并且完成id的回插
            proSetDao.insertProSet(proSet);
            int proserID=proSet.getId();
            //根据套题的id和习题的id进行插入
            SetAndExe setAndExe;
            //插入套题和习题的对应信息
            List<Integer> exerIDs= proSet.getExerciseList();
            int size=exerIDs.size();
            for(int i=0;i<size;i++){
                setAndExe=new SetAndExe();
                setAndExe.prosetID=proserID;
                setAndExe.exerciseID=exerIDs.get(i);
                setAndExeDao.insert(setAndExe);
            }
        }catch(Exception e){
                throw new AIstudyException(AIstudyException.ErrorType.INSERT_ERROR,"添加套题信息失败");
        }
    }
    public ProSet findProsetByID(Integer prosetID){
        return proSetDao.selectById(prosetID);
    }
    @Override
    public IPage<ProSet> findProset(Map<String, Object> condition, Integer pageNum, Integer pageSize) {
        IPage page = new Page(pageNum, pageSize);
        QueryWrapper<ProSet> qw = new QueryWrapper<>();
        qw.like(condition.containsKey("proSetName"), "proSetName", condition.get("proSetName"));
        //学生查询问题信息的时候可以筛选
        qw.like(condition.containsKey("proSetDesc"), "proSetDesc", condition.get("proSetDesc"));
        qw.eq(condition.containsKey("stuID"), "teacherID", condition.get("teacherID"));
        //按照排序查询套题记录
        if(condition.containsKey("orderField")){
            String orderField=condition.get("orderField").toString();
            //当排序的类型不为空，且为降序的时候，按照降序排列
            if(condition.get("orderType").equals("ASC")){
                qw.orderByAsc(orderField);
            }
            //当排序的类型为空，或指明升序，则按升序排列
            else{
                qw.orderByDesc(orderField);
            }
        }
//        //对点赞进行处理，如果已经点赞过，则这里表示为true
//        List<Integer>like=likedDao.getlikeList((Integer) condition.get("teacherID"));
//        IPage<ProSet> ipage=proSetDao.findProset(page, qw);
//        List<ProSet>sets=ipage.getRecords();
//        int size=sets.size();
//        for(int i=0;i<size;i++){
//            if(like.contains(sets.get(i).getId())){
////                sets.get(i).setLiked(true);
//            }
//        }
//        ipage.setRecords(sets);
        return proSetDao.findProset(page, qw);
    }

    @Override
    @Transactional(rollbackFor = AIstudyException.class)
    public void updateProset(ProSet proSet) throws AIstudyException{
        try{
            //更新套题的信息
            proSetDao.updateById(proSet);
            int proserID=proSet.getId();
            //删除对应关系
            setAndExeDao.deleteBySetID(proserID);
            SetAndExe setAndExe;
            //插入套题和习题的对应信息，先删除后增加，可以不用判断那么多
            List<Integer> exerIDs= proSet.getExerciseList();
            int size=exerIDs.size();
            for(int i=0;i<size;i++){
                setAndExe=new SetAndExe();
                setAndExe.prosetID=proserID;
                setAndExe.exerciseID=exerIDs.get(i);
                setAndExeDao.insert(setAndExe);
            }
        }catch (Exception e){
            throw new AIstudyException(AIstudyException.ErrorType.UPDATE_ERROR,"更新套题信息失败");
        }
    }

    @Override
    @Transactional(rollbackFor = AIstudyException.class)
    public void deleteProset(int prosetID)  throws AIstudyException{
        try{
            //删除对应关系
            setAndExeDao.deleteBySetID(prosetID);
            //删除试题信息
            proSetDao.deleteById(prosetID);
        }catch (Exception e){
            throw new AIstudyException(AIstudyException.ErrorType.DELETE_ERROR,"删除套题信息失败");
        }
    }

    //获取套题的所有单题、作文和翻译
    public List<Exercise> findProsetSingleExe(int prosetID,String category){
        return proSetDao.findProsetSingleExe(prosetID,category);
    }

    //获取套题的所有大题（包含多道小题）
    public List<Exercise> findProsetNoSingleExe(int prosetID,String category){
        return proSetDao.findProsetNoSingleExe(prosetID,category);
    }

    //增加点赞记录，更新套题点赞信息
    @Transactional(rollbackFor = AIstudyException.class)
    public void insertLiked(Liked liked)throws AIstudyException{
        try{
            likedDao.insert(liked);
            ProSet proSet=proSetDao.selectById(liked.getProsetID());
//            proSet.setStar(proSet.getStar()+1);
            proSetDao.updateById(proSet);
        }catch (Exception e){
            throw new AIstudyException(AIstudyException.ErrorType.INSERT_ERROR,"增加点赞信息失败");
        }
    }
    @Transactional(rollbackFor = AIstudyException.class)
    public void InsertSingleExercise(List<Exercise>exercises,int score,int proserID){
        int size=exercises.size();
        SetAndExe setAndExe;
        for(int i=0;i<size;i++){
            if(!exercises.get(i).isExisted()){
                exeDao.insert(exercises.get(i));
            }
            setAndExe=new SetAndExe();
            setAndExe.prosetID=proserID;
            setAndExe.exerciseID=exercises.get(i).getId();
            setAndExeDao.insert(setAndExe);
        }
    }

    @Transactional(rollbackFor = AIstudyException.class)
    public void insertNoSingleExercise(List<Exercise>exercises,int score,int proserID) throws AIstudyException {
        try{
            int size = exercises.size();
            //如果题在题库中不存在，则需要新增 题的信息
            if(!exercises.get(0).isExisted()) {
                StringBuilder sonProID = new StringBuilder();
                //首先插入子题，获取每个子题的id，并且封装成一个字符串
                exeDao.insertExercise(exercises.get(1));
                sonProID.append(exercises.get(1).getId());
                for (int i = 2; i < size; i++) {
                    exeDao.insertExercise(exercises.get(i));
                    sonProID.append("," + exercises.get(i).getId());
                }
                //设置大题中第一题的子题字符串后再插入
                exercises.get(0).setSonProID(String.valueOf(sonProID));
                exeDao.insertExercise(exercises.get(0));
            }
            //将题与套题进行关联操作
            SetAndExe setAndExe;
            for(int i=0;i<size;i++){
                setAndExe=new SetAndExe();
                setAndExe.prosetID=proserID;
                setAndExe.exerciseID=exercises.get(i).getId();
                setAndExeDao.insert(setAndExe);
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new AIstudyException(AIstudyException.ErrorType.INSERT_ERROR,"添加习题失败");
        }
    }
    @Transactional(rollbackFor = AIstudyException.class)
    public void insertProsetDetail( ProsetDTO prosetDTO) throws AIstudyException{
        try{
                ProSet proSet=prosetDTO.getTestProps();
                //插入套题的相关信息
                proSetDao.insert(proSet);
                //获取到套题的ID
                prosetDTO.getTestProps().setId(proSet.getId());
            manageProsetDetail(prosetDTO);
        }catch (Exception e){
            throw new AIstudyException(AIstudyException.ErrorType.INSERT_ERROR,"增加套题详细信息失败");
        }
    }
        @Transactional(rollbackFor = AIstudyException.class)
        public void manageProsetDetail(ProsetDTO prosetDTO) throws AIstudyException {
                //获取套题的ID
            int proserID=prosetDTO.getTestProps().getId();
            Map<String,List<Exercise>>question=prosetDTO.getQuestion();

            //插入选择题，如果不存在则进行添加操作
            List<Exercise>exercises=question.get("xuanze");
            int score=prosetDTO.getXuanzeScore();
            InsertSingleExercise(exercises,score,proserID);

            //插入翻译题，如果不存在则进行添加操作
            exercises=question.get("fanyi");
            score=prosetDTO.getFanyiScore();
            InsertSingleExercise(exercises,score,proserID);

            //插入作文题，如果不存在则进行添加操作
            exercises=question.get("zuowen");
            score=prosetDTO.getZuoWenScore();
            InsertSingleExercise(exercises,score,proserID);

            //插入阅读信息
            exercises=question.get("yuedu");
            score=prosetDTO.getYueduScore();
            int size=exercises.size();
            List<Exercise>tmp=new ArrayList<>();
            //遍历每一个阅读信息，进行插入
            for(int i=0;i<size;i++){
                tmp.clear();
                tmp.add(exercises.get(i));
                tmp.addAll(exercises.get(i).getSonExercise());
                insertNoSingleExercise(tmp,score,proserID);
            }
            //插入完形的信息
            exercises=question.get("wanxing");
            score=prosetDTO.getWanxingScore();
            size=exercises.size();
            tmp=new ArrayList<>();
            for(int i=0;i<size;i++){
                tmp.clear();
                tmp.add(exercises.get(i));
                tmp.addAll(exercises.get(i).getSonExercise());
                insertNoSingleExercise(tmp,score,proserID);
            }
            exercises=question.get("xuanci");
            score=prosetDTO.getXuanciScore();
            size=exercises.size();
            tmp=new ArrayList<>();
            for(int i=0;i<size;i++){
                tmp.clear();
                tmp.add(exercises.get(i));
                tmp.addAll(exercises.get(i).getSonExercise());
                insertNoSingleExercise(tmp,score,proserID);
            }
        }
    @Transactional(rollbackFor = AIstudyException.class)
    public void updateProsetDetail( ProsetDTO prosetDTO) throws AIstudyException{
        try{
                setAndExeDao.deleteBySetID(prosetDTO.getTestProps().getId());
                proSetDao.updateById(prosetDTO.getTestProps());
                manageProsetDetail(prosetDTO);
        }catch (Exception e){
            throw new AIstudyException(AIstudyException.ErrorType.INSERT_ERROR,"更新套题详细信息失败");
        }
    }
}
